#include "app_device.h"

static Device *device;

// 线程从缓冲区读取数据,写入蓝牙文件
static void app_device_write_task(void *)
{
    // 1.从下行缓冲区读取数据
    char data_buffer[256];
    int data_len = app_buffer_read(device->down_buffer, data_buffer, 256);
    if (data_len <= 0)
    {
        log_info("从下行缓冲区读取数据失败!");
        return;
    }

    // 2.两次写入需要间隔最少200ms
    unsigned long long time_diff = app_common_GetCurrentTime() - device->last_write_time;
    log_info("cur_ts = %llu,last_ts = %llu,diff_ts = %llu",
             app_common_GetCurrentTime(),
             device->last_write_time,
             time_diff);
    if (time_diff < 200)
    {
        // 等待一会
        // sleep(1);
        usleep((200 - time_diff) * 1000);
    }

    // 3.将读取到的数据写入蓝牙文件
    ssize_t write_len = write(device->fd, data_buffer, data_len);
    if (write_len != data_len)
    {
        log_info("数据写入蓝牙文件失败!");
        return;
    }

    // 4.修改上一次写入时间
    device->last_write_time = app_common_GetCurrentTime();

    log_info("数据写入蓝牙文件成功!data = %.*s", data_len, data_buffer);
}

// MQTT回调函数 json_str:{"conn_type":1,"id":"5858","msg":"61626364"}
int app_device_rece_cb(char *json_str)
{
    // 将json格式数据转换为字符数组
    char chars_buffer[256];
    int chars_len = app_message_JsonStrToChars(json_str, chars_buffer, sizeof(chars_buffer));
    if (chars_len <= 0)
    {
        log_info("JSON数据解析失败!");
        return -1;
    }

    // 判断是否需要进行写缓冲区前预处理
    if (device->pre_write)
    {
        // chars_buffer:01 02 04 58 58 61 62 63 64
        chars_len = device->pre_write(chars_buffer, chars_len);
    }

    // 将数据写入下行缓冲区 chars_buffer:AT+MESH 0xFF 0xFF abcd \r\n
    int result = app_buffer_write(device->down_buffer, chars_buffer, chars_len);
    if (result == -1)
    {
        log_info("写入缓冲区失败!");
        return -1;
    }

    // 将下发数据(将数据写入蓝牙文件)操作交给线程池
    app_pool_add_task(app_device_write_task, NULL);

    return 0;
}

// 初始化设备
Device *app_device_init(char *file_name)
{
    // 1.给设备申请内存
    device = malloc(sizeof(Device));

    // 2.给设备属性赋值
    device->filename = file_name;
    device->fd = open(file_name, O_RDWR | O_APPEND);
    device->up_buffer = app_buffer_init(1024);
    device->down_buffer = app_buffer_init(1024);
    // device->read_thread = NULL;
    device->is_running = 0;
    device->last_write_time = 0;
    // device->post_read = NULL;
    // device->pre_write = NULL;

    // 3.初始化线程池
    app_pool_init(5);

    // 4.初始化MQTT模块
    app_mqtt_init(app_device_rece_cb);

    // 5.返回结果
    return device;
}

// 从缓冲区读取数据发送至MQTT服务器函数
void app_device_send_task_func(void *args)
{
    // 从上行缓冲区中读取数据
    char data_buffer[256];
    int read_len = app_buffer_read(device->up_buffer, data_buffer, 256);
    if (read_len == -1)
    {
        log_info("从上行缓冲区中读取数据失败!");
        return;
    }

    // 将字符数组转换为JSON字符串
    char *json_str = app_message_CharsToJsonStr(data_buffer, read_len);

    // 调用MQTT客户端上传数据
    int result = app_mqtt_send(json_str);
    if (result == -1)
    {
        log_info("调用MQTT客户端上传数据失败!");
        return;
    }

    free(json_str);
    log_info("调用MQTT客户端上传数据成功!");
}

// 读取蓝牙文件的线程
static void *app_device_read_thread_func(void *args)
{
    while (device->is_running)
    {
        // 读取文件
        char data_buffer[256];
        ssize_t data_len = read(device->fd, data_buffer, 256);

        // 判断如果读取到数据则处理
        if (data_len > 0 && device->post_read)
        {
            data_len = device->post_read(data_buffer, data_len);
        }

        if (data_len > 0)
        {
            log_info("处理后的数据长度为:%d", data_len);
            // 将数据写入上行缓冲区
            int result = app_buffer_write(device->up_buffer, data_buffer, data_len);
            if (result == -1)
            {
                log_info("将数据写入上行缓冲区失败!");
            }
            else
            {
                log_info("将数据写入上行缓冲区成功!");
                app_pool_add_task(app_device_send_task_func, NULL);
            }
        }
    }

    return NULL;
}

/**
 * 启动设备:本质就是启动读取文件的线程
 */
void app_device_start(void)
{
    // 判断设备是否已经启动
    if (device->is_running)
    {
        log_info("设备已启动!");
        return;
    }

    // 修改设备的启动状态
    device->is_running = 1;

    // 创建读取蓝牙文件的线程
    pthread_create(&device->read_thread, NULL, app_device_read_thread_func, NULL);
}

// 关闭设备,释放内存
void app_device_close(void)
{
    // 关闭文件流
    close(device->fd);

    // 释放缓冲区内存
    app_buffer_deinit(device->up_buffer);
    app_buffer_deinit(device->down_buffer);

    // 取消读取数据线程
    pthread_cancel(device->read_thread);

    device->is_running = 0;

    // 释放当前设备
    free(device);

    // 关闭线程池
    app_pool_close();
}